﻿// (c)2010 David Schwarz (david.schwarz@live.com)
// This file is licensed under GNU GPL v2 license, see more at http://www.gnu.org/licenses/gpl-2.0.html
namespace Z2.Core
{

	#region Using

	using System;
	using Microsoft.Xna.Framework;
	using System.Diagnostics;
	using System.Collections.Generic;

	#endregion

	/// <summary>
	/// Třída definující standrdní chování objektu (působící gravitace)
	/// </summary>
	internal class ParticleBehavior : ObjectBehaviorBase
	{

		#region Const

		private const float GRAVITY_MAX = 10.0f;
		private const float GRAVITY_DEFAULT = 0.1f;
		private const float GRAVITY_BOOST = 0.8f;
		
		#endregion

		private float m_lightend;

		#region Constructor

		/// <summary>
		/// Konstruktor
		/// </summary>
		public ParticleBehavior()
			: this(0)
		{
		}

		public ParticleBehavior(float lightend)
			: base()
		{
			m_lightend = lightend;
		}

		#endregion

		#region Override Methods

		private bool CantCollide(ObjectBase thisObj, ObjectBase obj)
		{
			return obj == thisObj || obj is ParticleBasic || obj is Player || obj is ItemBase || thisObj.CantCollide(obj);
		}

		/// <summary>
		/// Metoda, která modifikuje vektor pohybu objektu <paramref name="obj"/>
		/// </summary>
		/// <param name="obj"><see cref="ObjectBase"/></param>
		internal override void ModifyVector(ObjectBase obj)
		{
			float boost = GRAVITY_BOOST - m_lightend;

			// Změna vektoru v ose X & Ošetření maximální rychlosti v ose X
			if (obj.Change.X != 0)
			{
				obj.Move = new Vector2(obj.Move.X + obj.Change.X, obj.Move.Y);
				if (obj.MaxHorizontalSpeed > 0 && Math.Abs(obj.Move.X) > obj.MaxHorizontalSpeed)
				{
					obj.Move = new Vector2(obj.Move.X > 0 ? obj.MaxHorizontalSpeed : -obj.MaxHorizontalSpeed, obj.Move.Y);
				}
			}

			Rectangle rect;
			IntersectionResult ir;
			List<ObjectBase> objects = World.Current.GetSectorsObjects(obj, CantCollide);
			bool cwo = false;

			// Check for gravity
			rect = obj.GetRectangle(0, obj.Move.Y + boost);

			ir = World.Current.Intersects(obj, rect, true);
			if (!ir.IsCollision)
			{
				foreach (ObjectBase objBase in objects)
				{
					if (CantCollide(obj, objBase)) continue;

					ir = obj.Intersects(objBase, rect);
					if (ir.IsCollision)
					{
						cwo = true;
						break;
					}
				}
			}
			else
			{
				cwo = true;
			}

			if (cwo)
			{
				if (obj.VerticalState != ObjectStateVertical.Idle)
				{
					obj.VerticalState = ObjectStateVertical.Idle;
					obj.OnStopMovingVertical();
				}
				obj.Move = new Vector2(obj.Move.X, -(obj.Move.Y/2));
			}
			else
			{
				obj.Move = new Vector2(obj.Move.X, obj.Move.Y + boost);
			}

			cwo = false;

			// Horizontal
			//if (obj.Move.X != 0)
			{
				rect = obj.GetRectangle(obj.Move.X, 0);

				ir = World.Current.Intersects(obj, rect, false);
				if (!ir.IsCollision)
				{
					foreach (ObjectBase objBase in objects)
					{
						if (CantCollide(obj, objBase)) continue;

						ir = obj.Intersects(objBase, rect);
						if (ir.IsCollision)
						{
							cwo = true;
							break;
						}
					}
				}
				else
				{
					cwo = true;
				}

				if (cwo)
					obj.Move = new Vector2(-obj.Move.X/2, obj.Move.Y);
				else
					obj.Position = new Vector2(obj.Position.X + obj.Move.X, obj.Position.Y);

				cwo = false;
			}

			// Vertical
			//if (obj.Move.Y != 0)
			{
				rect = obj.GetRectangle(0, obj.Move.Y);
					
				ir = World.Current.Intersects(obj, rect, true);
				if (!ir.IsCollision)
				{
					foreach (ObjectBase objBase in objects)
					{
						if (CantCollide(obj, objBase)) continue;

						ir = obj.Intersects(objBase, rect);
						if (ir.IsCollision)
						{
							cwo = true;
							break;
						}
					}
				}
				else
				{
					cwo = true;
				}

				if (cwo)
				{
					if (obj.VerticalState != ObjectStateVertical.Idle)
					{
						obj.VerticalState = ObjectStateVertical.Idle;
						obj.OnStopMovingVertical();
					}
					obj.Move = new Vector2(obj.Move.X, 0);
				}
				else
				{
					obj.Position = new Vector2(obj.Position.X, obj.Position.Y + obj.Move.Y);
				}
			}
		}

		#endregion

	}
}
